home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / eulisp / feel0_89.lha / Feel / Src / sockets.c < prev    next >
C/C++ Source or Header  |  1993-07-01  |  16KB  |  659 lines

  1. /* ******************************************************************** */
  2. /* sockets.c         Copyright (C) Codemist and University of Bath 1989 */
  3. /*                                                                      */
  4. /* Inter-processes communication                                    */
  5. /* ******************************************************************** */
  6.  
  7. #define PAUSE() 
  8.  
  9. /*
  10.  * Change Log:
  11.  *   Version 1, June 1990
  12.  */
  13.  
  14. static char *woo_woo = "WOO! WOO!"; /* To appease ncc */
  15.  
  16. #if (defined(WITH_BSD_SOCKETS) || defined(WITH_SYSTEMV_SOCKETS))
  17.  
  18. #include "funcalls.h"
  19. #include "defs.h"
  20. #include "structs.h"
  21. #include "error.h"
  22. #include "global.h"
  23.  
  24. #include "calls.h"
  25. #include "modboot.h"
  26. #include "allocate.h"
  27. #include "modules.h"
  28.  
  29. #include "symboot.h"
  30. #include "syssockets.h"
  31. #include "sio.h"
  32. #include "class.h"
  33.  
  34. /*
  35.  
  36.  * Socket stuff... 
  37.  
  38.  */
  39.  
  40. /* Globals... */
  41.  
  42. SYSTEM_GLOBAL(char *,host_machine_name);
  43. SYSTEM_GLOBAL(Host *,host_machine_ref);
  44. SYSTEM_GLOBAL(LispObject,host_machine_lisp_name);
  45.  
  46. /* classes */
  47. static LispObject Socket;
  48. static LispObject Listener;
  49.  
  50. #define NO_CHAR -1
  51.  
  52. EUFUN_1( Fn_listernerp, obj)
  53. {
  54.   return((is_listener(obj) ? lisptrue : nil));
  55. }
  56. EUFUN_CLOSE
  57.  
  58. EUFUN_1( Fn_socketp, obj)
  59. {
  60.   return((is_socket(obj) ? lisptrue : nil));
  61. }
  62. EUFUN_CLOSE
  63.  
  64. EUFUN_0( Fn_make_listener)
  65. {
  66.   LispObject listener;
  67.   int length;
  68.   int port;
  69.  
  70.   listener = allocate_listener(stacktop);
  71.  
  72.   if ((listener->LISTENER.socket = socket(AF_INET,SOCK_STREAM,0)) < 0) 
  73.     CallError(stacktop,
  74.           "make-;istener: unable to make socket",nil,NONCONTINUABLE);
  75.  
  76.   /* Bind it to look for anything... */
  77.  
  78.   listener->LISTENER.name.sin_family = AF_INET;
  79.   listener->LISTENER.name.sin_addr.s_addr = INADDR_ANY;
  80.   listener->LISTENER.name.sin_port = 0;
  81.  
  82.   length = sizeof(SocketInName);
  83.  
  84.   if (bind(listener->LISTENER.socket,
  85.        (SocketName *) &(listener->LISTENER.name),
  86.        length) < 0)
  87.     CallError(stacktop,"make-listener: can't bind socket",nil,NONCONTINUABLE);
  88.  
  89.   if (getsockname(listener->LISTENER.socket,
  90.           (SocketName *) &(listener->LISTENER.name),
  91.           &length) < 0)
  92.     CallError(stacktop,
  93.           "make-listener: can't get socket data",nil,NONCONTINUABLE);
  94.  
  95.   listener->LISTENER.state = SOCKET_VIRGIN;
  96.  
  97.   listen(listener->LISTENER.socket,5); /* One step at a time... */
  98.  
  99.   lval_classof(listener) = Listener; 
  100.   return(listener);
  101. }
  102. EUFUN_CLOSE
  103.  
  104. EUFUN_0( Fn_make_socket)
  105. {
  106.   LispObject lispsock;
  107.  
  108.   lispsock = allocate_socket(stacktop);
  109.  
  110.   if ((lispsock->SOCKET.socket = socket(AF_INET,SOCK_STREAM,0)) < 0)
  111.     CallError(stacktop,
  112.           "make-socket: unable to make socket",nil,NONCONTINUABLE);
  113.  
  114.   lispsock->SOCKET.state = SOCKET_VIRGIN;
  115.   
  116.   lval_classof(lispsock) = Socket;
  117.  
  118.   return(lispsock);
  119. }
  120. EUFUN_CLOSE
  121.   
  122. EUFUN_1( Fn_listener_id, sock)
  123. {
  124.   LispObject data;
  125.  
  126.   if (!is_listener(sock))
  127.     CallError(stacktop,"listener-id: not a listener",sock,NONCONTINUABLE);
  128.  
  129.   if (sock->LISTENER.state != SOCKET_VIRGIN)
  130.     CallError(stacktop,"listener-id: socket not virgin ",sock,NONCONTINUABLE);
  131.  
  132.   /* Should lock it for parallel safety I suppose... */
  133.  
  134.   /* Build a list of host machine and port number... */
  135.  
  136.   if (ntohs(sock->LISTENER.name.sin_port) > 0x7ffffff)
  137.     CallError(stacktop,
  138.           "listener-id: port number overflow!",sock,NONCONTINUABLE);
  139.  
  140.   STACK(sock);
  141.  
  142.   data = (LispObject)
  143.          allocate_integer(stacktop,(int) ntohs(sock->LISTENER.name.sin_port));
  144.   EUCALLSET_2(data , Fn_cons, SYSTEM_GLOBAL_VALUE(host_machine_lisp_name),
  145.           data);
  146.  
  147.   return(data);
  148. }
  149. EUFUN_CLOSE
  150.  
  151. EUFUN_1( Fn_listen, sock)
  152. {
  153.   LispObject new;
  154.   int length;
  155.  
  156.   if (!is_listener(sock))
  157.     CallError(stacktop,"listen: not a listener",sock,NONCONTINUABLE);
  158.  
  159.   if (sock->LISTENER.state != SOCKET_VIRGIN)
  160.     CallError(stacktop,"listen: listener not virgin",sock,NONCONTINUABLE);
  161.  
  162.   /* All is cool... */
  163.  
  164.   sock->LISTENER.state = SOCKET_LISTENING;
  165.  
  166.   sock->LISTENER.state = SOCKET_VIRGIN;
  167.  
  168.   /* Give back a 'copy'... */
  169.  
  170.   new = allocate_socket(stacktop);
  171.   lval_classof(new) = Socket; 
  172.  
  173.   new->SOCKET.state = SOCKET_CONNECTED;
  174.  
  175.   length = sizeof(SocketInName);
  176.  
  177.   new->SOCKET.socket = accept(sock->SOCKET.socket,
  178.                   (SocketName *) &(new->SOCKET.name),
  179.                   &length);
  180.  
  181.   if (new->SOCKET.socket < 0)
  182.     CallError(stacktop,"listen: unable to accept connection"
  183.           ,sock,NONCONTINUABLE);
  184.  
  185.   /* All is cool I think... */
  186.  
  187.   return(new);
  188. }
  189. EUFUN_CLOSE
  190.  
  191. EUFUN_1( Fn_connect, data)
  192. {
  193.   LispObject sock;
  194.   LispObject hostname,port;
  195.   Host *hostptr;
  196.   SocketInName their_name;
  197.  
  198.   if (!is_cons(data))
  199.     CallError(stacktop,"connect: invalid socket data",data,NONCONTINUABLE);
  200.  
  201.   hostname = CAR(data); port = CDR(data);
  202.  
  203.   if (!is_symbol(hostname) || !is_fixnum(port))
  204.     CallError(stacktop,"connect: invalid data elts",data,NONCONTINUABLE);
  205.  
  206.   /* Hokay... */
  207.  
  208.   STACK_TMP(port);
  209.   STACK_TMP(hostname);
  210.   sock = allocate_socket(stacktop);
  211.   UNSTACK_TMP(hostname);
  212.   UNSTACK_TMP(port);
  213.   lval_classof(sock) = Socket; 
  214.  
  215.   if ((sock->SOCKET.socket = socket(AF_INET,SOCK_STREAM,0)) < 0)
  216.     CallError(stacktop,"connect: can't get socket",data,NONCONTINUABLE);
  217.  
  218.   hostptr = gethostbyname(stringof(hostname->SYMBOL.pname));
  219.  
  220.   if (hostptr == NULL)
  221.     CallError(stacktop,"connect: unknown host",hostname,NONCONTINUABLE);
  222.  
  223.   bcopy((char *) (hostptr->h_addr),
  224.     (char *) &(their_name.sin_addr),
  225.     hostptr->h_length);
  226.   their_name.sin_family = AF_INET;
  227.   their_name.sin_port = htons(intval(port));
  228.  
  229.   if (connect(sock->SOCKET.socket,
  230.           (SocketName *) &their_name,
  231.           sizeof(their_name)) < 0) 
  232.     CallError(stacktop,"socket-connect: can't connect",data,NONCONTINUABLE);
  233.   
  234.   /* All is cool (hopefully)... */
  235.  
  236.   sock->SOCKET.state = SOCKET_CONNECTED;
  237.   sock->SOCKET.lastchar=NO_CHAR;
  238.  
  239.   return(sock);
  240. }
  241. EUFUN_CLOSE
  242.  
  243. EUFUN_1( Fn_close_listener, list)
  244. {
  245.   if (!is_listener(list))
  246.     CallError(stacktop,"close-listener: not a listeners",list,NONCONTINUABLE);
  247.  
  248.   if (list->LISTENER.state != SOCKET_VIRGIN)
  249.     CallError(stacktop,"close-listener: not virgin",list,NONCONTINUABLE);
  250.  
  251. #ifdef notdef
  252. /**/  These lines cause trouble on stardents...
  253. /**/  shutdown(list->LISTENER.socket,2);
  254. /**/
  255. /**/  close(list->LISTENER.socket);
  256. #endif
  257.   list->LISTENER.state = SOCKET_CLOSED;
  258.  
  259.  
  260.   return(nil);
  261. }
  262. EUFUN_CLOSE
  263.  
  264. EUFUN_1( Fn_close_socket, sock)
  265. {
  266.   if (!is_socket(sock))
  267.     CallError(stacktop,"close-socket: not a socket",sock,NONCONTINUABLE);
  268.  
  269.   if (sock->SOCKET.state != SOCKET_VIRGIN
  270.       && sock->SOCKET.state != SOCKET_CONNECTED)
  271.     CallError(stacktop,"close-socket: not virgin",sock,NONCONTINUABLE);
  272.  
  273.   shutdown(sock->SOCKET.socket,2);
  274.  
  275.   close(sock->SOCKET.socket);
  276.  
  277.   sock->SOCKET.state = SOCKET_CLOSED;
  278.  
  279.   return(nil);
  280. }
  281. EUFUN_CLOSE
  282.  
  283. EUFUN_2( Fn_socket_write, sock, form)
  284. {
  285.   if (!is_socket(sock))
  286.     CallError(stacktop,"socket-write: not a socket",sock,NONCONTINUABLE);
  287.  
  288.   if (sock->SOCKET.state != SOCKET_CONNECTED)
  289.     CallError(stacktop,
  290.           "socket-write: socket not connected",sock,NONCONTINUABLE);
  291.  
  292.   /* Set up the buffer... */
  293.  
  294.   BUFFER_FORM() = form;
  295.   BUFFER_PTR() = 0;
  296.  
  297.   /* Write form... */
  298.  
  299.   write_object(stacktop,form);
  300.   *(BUFFER()) = '\0';
  301.  
  302. /*  fprintf(stderr,"written: '%s'\n",BUFFER_START()); */
  303.  
  304.   /* OK, now flush the socket... */
  305.  
  306.   /* catch busted pipe signals */
  307.   
  308.   write(sock->SOCKET.socket,(char *) &(BUFFER_PTR()),sizeof(int));
  309.   write(sock->SOCKET.socket,BUFFER_START(),BUFFER_PTR());
  310.  
  311.   return(form);
  312. }
  313. EUFUN_CLOSE
  314.  
  315. EUFUN_2(Fn_socket_write_string,sock,form)
  316. {
  317.   if (!is_socket(sock))
  318.     CallError(stacktop,"socket-write: not a socket",sock,NONCONTINUABLE);
  319.   
  320.   if (sock->SOCKET.state != SOCKET_CONNECTED)
  321.     CallError(stacktop,
  322.           "socket-write: socket not connected",sock,NONCONTINUABLE);
  323.  
  324.   if (write(sock->SOCKET.socket,stringof(form),strlen(stringof(form))) < 0)
  325.     {
  326.       perror("socket_write");
  327.       return nil;
  328.     }
  329.   else
  330.     return lisptrue;
  331. }
  332. EUFUN_CLOSE
  333. #ifdef WITH_SYSTEMV_SOCKETS
  334.  
  335. #include <stropts.h>
  336. #include <poll.h>
  337.  
  338. EUFUN_1( Fn_socket_readable_p, sock)
  339. {
  340.   struct pollfd fds[1];
  341.   unsigned long nfds = 1;
  342.  
  343.   if (!is_socket(sock))
  344.     CallError(stacktop,"socket-readable-p: not a socket",sock,NONCONTINUABLE);
  345.  
  346.   if (sock->SOCKET.state != SOCKET_CONNECTED)
  347.     CallError(stacktop,"socket-readable-p: not connected",sock,NONCONTINUABLE);
  348.  
  349.   fds[0].fd = sock->SOCKET.socket;
  350.   fds[0].events = POLLIN;
  351.   fds[0].revents = 0;
  352.  
  353.   if (poll(fds,nfds,0) < 0)
  354.     CallError(stacktop,"socket-readable-p: poll failed",sock,NONCONTINUABLE);
  355.  
  356.   if (fds[0].revents & POLLIN)
  357.     return(lisptrue);
  358.   else
  359.     return(nil);
  360. }
  361. EUFUN_CLOSE
  362.  
  363. EUFUN_1( Fn_listener_listenable_p, listener)
  364. {
  365.   struct pollfd fds[1];
  366.   unsigned long nfds = 1;
  367.  
  368.   if (!is_listener(listener))
  369.     CallError(stacktop,
  370.           "listener_listenable_p: not a listener",listener,NONCONTINUABLE);
  371.  
  372.   fds[0].fd = listener->SOCKET.socket;
  373.   fds[0].events = POLLIN;
  374.   fds[0].revents = 0;
  375.  
  376.   if (poll(fds,nfds,0) < 0)
  377.     CallError(stacktop,
  378.           "socket-readable-p: poll failed",listener,NONCONTINUABLE);
  379.  
  380.   if (fds[0].revents & POLLIN)
  381.     return(lisptrue);
  382.   else
  383.     return(nil);
  384. }
  385. EUFUN_CLOSE
  386.  
  387. EUFUN_1( Fn_socket_writable_p, sock)
  388. {
  389.   struct pollfd fds[1];
  390.   unsigned long nfds = 1;
  391.  
  392.   if (!is_socket(sock))
  393.     CallError(stacktop,"socket-writable-p: not a socket",sock,NONCONTINUABLE);
  394.  
  395.   if (sock->SOCKET.state != SOCKET_CONNECTED)
  396.     CallError(stacktop,"socket-writable-p: not connected",sock,NONCONTINUABLE);
  397.  
  398.   fds[0].fd = sock->SOCKET.socket;
  399.   fds[0].events = POLLOUT;
  400.   fds[0].revents = 0;
  401.  
  402.   if (poll(fds,nfds,0) < 0)
  403.     CallError(stacktop,"socket-writable-p: poll failed",sock,NONCONTINUABLE);
  404.  
  405.   if (fds[0].revents & POLLOUT)
  406.     return(lisptrue);
  407.   else
  408.     return(nil);
  409. }
  410. EUFUN_CLOSE
  411.  
  412. #else
  413.  
  414. /* BSD... */
  415.  
  416. #include <sys/time.h>
  417.  
  418. EUFUN_1( Fn_socket_readable_p, sock)
  419. {
  420.   fd_set mask;
  421.   struct timeval wait;
  422.  
  423.   if (!is_socket(sock))
  424.     CallError(stacktop,"socket-readable-p: not a socket",sock,NONCONTINUABLE);
  425.  
  426.   if (sock->SOCKET.state != SOCKET_CONNECTED)
  427.     CallError(stacktop,"socket-readable-p: not connected",sock,NONCONTINUABLE);
  428.  
  429.   /* Do a select with 0 timeout... */
  430.  
  431.   wait.tv_sec = 0;
  432.   wait.tv_usec = 0;
  433.  
  434.   FD_ZERO(&mask);
  435.   FD_SET(sock->SOCKET.socket,&mask);
  436.  
  437.   if (select(getdtablesize(),&mask,NULL,NULL,&wait) < 0)
  438.     CallError(stacktop,"socket-readable-p: select failed",sock,NONCONTINUABLE);
  439.  
  440.   if (FD_ISSET(sock->SOCKET.socket,&mask))
  441.     return(lisptrue);
  442.   else
  443.     return(nil);
  444.  
  445.   return(nil);
  446. }
  447. EUFUN_CLOSE
  448.  
  449. EUFUN_1( Fn_listener_listenable_p, listener)
  450. {
  451.   fd_set mask;
  452.   struct timeval wait;
  453.  
  454.   if (!is_listener(listener))
  455.     CallError(stacktop,
  456.           "socket-listenable-p: not a listener",listener,NONCONTINUABLE);
  457.  
  458.   /* Do a select with 0 timeout... */
  459.  
  460.   wait.tv_sec = 0;
  461.   wait.tv_usec = 0;
  462.  
  463.   FD_ZERO(&mask);
  464.   FD_SET(listener->LISTENER.socket,&mask);
  465.  
  466.   if (select(getdtablesize(),&mask,NULL,NULL,&wait) < 0)
  467.     CallError(stacktop,
  468.           "socket-readable-p: select failed",listener,NONCONTINUABLE);
  469.  
  470.   if (FD_ISSET(listener->LISTENER.socket,&mask))
  471.     return(lisptrue);
  472.   else
  473.     return(nil);
  474.  
  475.   return(nil);
  476. }
  477. EUFUN_CLOSE
  478.  
  479. EUFUN_1( Fn_socket_writable_p, sock)
  480. {
  481.   fd_set mask;
  482.   struct timeval wait;
  483.  
  484.   if (!is_socket(sock))
  485.     CallError(stacktop,
  486.           "socket-readable-p: not a socket",sock,NONCONTINUABLE);
  487.  
  488.   if (sock->SOCKET.state != SOCKET_CONNECTED)
  489.     CallError(stacktop,
  490.           "socket-readable-p: not connected",sock,NONCONTINUABLE);
  491.  
  492.   /* Do a select with 0 timeout... */
  493.  
  494.   wait.tv_sec = 0;
  495.   wait.tv_usec = 0;
  496.  
  497.   FD_ZERO(&mask);
  498.   FD_SET(sock->SOCKET.socket,&mask);
  499.  
  500.   if (select(getdtablesize(),NULL,&mask,NULL,&wait) < 0)
  501.     CallError(stacktop,"socket-readable-p: select failed",sock,NONCONTINUABLE);
  502.  
  503.   if (FD_ISSET(sock->SOCKET.socket,&mask))
  504.     return(lisptrue);
  505.   else
  506.     return(nil);
  507.  
  508.   return(nil);
  509.  
  510. }
  511. EUFUN_CLOSE
  512.  
  513. #endif
  514.  
  515. EUFUN_1( Fn_socket_read, sock)
  516. {
  517.   int len,ret;
  518.   LispObject obj;
  519.  
  520.   if (!is_socket(sock))
  521.     CallError(stacktop,"socket-read: not a socket",sock,NONCONTINUABLE);
  522.  
  523.   if (sock->SOCKET.state != SOCKET_CONNECTED)
  524.     CallError(stacktop,"socket-read: not connected",sock,NONCONTINUABLE);
  525.  
  526. #ifdef NOTDEFINED    /* Allow this call to block */
  527.   if (Fn_socket_readable_p(sock) == nil)
  528.     CallError(stacktop,"socket-read: socket unreadable",sock,NONCONTINUABLE);
  529. #endif
  530.  
  531.   /* Get the length... */
  532.  
  533.   if ( (ret = read(sock->SOCKET.socket,(char *) &len,sizeof(int))) == -1)
  534.     {
  535.       CallError(stacktop,
  536.         "socket-read: could not read socket",sock,NONCONTINUABLE);
  537.     }
  538.  
  539.   /* Read the data... */
  540.  
  541.   if ((ret = read(sock->SOCKET.socket,(char *) (BUFFER_START()),len)) == -1)
  542.     {
  543.       CallError(stacktop,
  544.         "socket-read: could not complete socket-read",
  545.         sock,NONCONTINUABLE);
  546.     }
  547.  
  548. /*  fprintf(stderr,"read: '%s'\n",BUFFER_START()); */
  549.  
  550.   *(BUFFER_START() + len) = '\0';
  551.   *(BUFFER_START() + len + 1) = '\n';
  552.  
  553.   /* Set up buffer... */
  554.  
  555.   BUFFER_PTR() = 0;
  556.  
  557.   obj = read_object(stacktop);
  558.  
  559.   return(obj);
  560. }
  561. EUFUN_CLOSE
  562.  
  563. static EUFUN_1(Fn_socket_read_char,sock)
  564. {
  565.   char x;
  566.   int ret;
  567.  
  568.   if (!is_socket(sock))
  569.     CallError(stacktop,"socket-read-char: not a socket",sock,NONCONTINUABLE);
  570.   
  571.   if (sock->SOCKET.lastchar==NO_CHAR)
  572.     {
  573.       ret=read(sock->SOCKET.socket,&x,1);
  574.       if (ret==0)
  575.     return q_eof;
  576.       else
  577.     return allocate_char(stacktop,x);
  578.     }
  579.   else
  580.     {
  581.       x=sock->SOCKET.lastchar;
  582.       sock->SOCKET.lastchar=NO_CHAR;
  583.       return allocate_char(stacktop,x);
  584.     }
  585. }
  586. EUFUN_CLOSE
  587.  
  588. static EUFUN_2(Fn_socket_unread_char,sock,c)
  589. {
  590.   if (!is_socket(sock))
  591.     CallError(stacktop,"socket-read-char: not a socket",sock,NONCONTINUABLE);
  592.   
  593.   if (sock->SOCKET.lastchar!=NO_CHAR)
  594.     CallError(stacktop,"socket-unread: can't unread further",sock,NONCONTINUABLE);
  595.   else
  596.     sock->SOCKET.lastchar=c->CHAR.code;
  597.   
  598.   return nil;
  599. }
  600. EUFUN_CLOSE
  601. /* *************************************************************** */
  602. /* Initialisation of this section                                  */
  603. /* *************************************************************** */
  604.  
  605.  
  606. #define SOCKETS_ENTRIES 18
  607. MODULE Module_sockets;
  608. LispObject Module_sockets_values[SOCKETS_ENTRIES];
  609.  
  610. void initialise_sockets(LispObject *stacktop)
  611. {
  612.   extern LispObject Standard_Class,Object, Primitive_Class;
  613.  
  614.   Socket = (LispObject) allocate_class(stacktop,NULL);
  615.   add_root(&Socket);
  616.   Listener = (LispObject) allocate_class(stacktop,NULL);    
  617.   add_root(&Listener);
  618.  
  619.   SYSTEM_INITIALISE_GLOBAL(char *,host_machine_name,NULL);
  620.   SYSTEM_INITIALISE_GLOBAL(Host *,host_machine_ref,NULL);
  621.   SYSTEM_INITIALISE_GLOBAL(LispObject,host_machine_lisp_name,NULL);
  622.   ADD_SYSTEM_GLOBAL_ROOT(host_machine_lisp_name);
  623.  
  624.   SYSTEM_GLOBAL_VALUE(host_machine_name) = (char *) malloc(64);
  625.   gethostname(SYSTEM_GLOBAL_VALUE(host_machine_name),64);
  626.  
  627.   SYSTEM_GLOBAL_VALUE(host_machine_lisp_name)
  628.     = (LispObject) get_symbol(stacktop,SYSTEM_GLOBAL_VALUE(host_machine_name));
  629.  
  630.   open_module(stacktop,
  631.           &Module_sockets,Module_sockets_values,"sockets",SOCKETS_ENTRIES);
  632.   
  633.  
  634.   (void) make_module_function(stacktop,"socketp",Fn_socketp,1);
  635.   (void) make_module_function(stacktop,"make-listener",
  636.                   Fn_make_listener,0);
  637.   (void) make_module_function(stacktop,"make-socket",
  638.                   Fn_make_socket,0);
  639.   (void) make_module_function(stacktop,"listener-id",Fn_listener_id,1);
  640.   (void) make_module_function(stacktop,"listen",Fn_listen,1);
  641.   (void) make_module_function(stacktop,"connect",Fn_connect,1);
  642.   (void) make_module_function(stacktop,"close-listener",Fn_close_listener,1);
  643.   (void) make_module_function(stacktop,"close-socket",Fn_close_socket,1);
  644.   (void) make_module_function(stacktop,"socket-write",Fn_socket_write,2);
  645.   (void) make_module_function(stacktop,"socket-write-string",Fn_socket_write_string,2);
  646.   (void) make_module_function(stacktop,"socket-read",Fn_socket_read,1);
  647.   (void) make_module_function(stacktop,"socket-read-char",Fn_socket_read_char,1);
  648.   (void) make_module_function(stacktop,"socket-unread-char",Fn_socket_unread_char,2);
  649.   (void) make_module_function(stacktop,"socket-readable-p",Fn_socket_readable_p,1);
  650.   (void) make_module_function(stacktop,"socket-writable-p",Fn_socket_writable_p,1);
  651.   (void) make_module_function(stacktop,"listener-listenable-p",Fn_listener_listenable_p,1);
  652.   (void) make_module_entry(stacktop,"<listener>",Listener);
  653.   (void) make_module_entry(stacktop,"<socket>",Socket);
  654.   close_module();
  655.  
  656. }
  657.  
  658. #endif
  659.